/*! ******************************************************************************
 *
 * Created on 2022年3月3日
 *
 * Copyright(c) YuZhou Big Data Laboratory CO.,Ltd, 2022.  All rights reserved.
 *
 *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/
package org.yzbdl.lanius.ui.spoon.middle.ext.progress;

import java.util.Map;
import java.util.Set;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import cn.hutool.core.lang.func.Func;

/**
 * 进度中心
 * 
 * @author hs@yzbdl.ac.cn
 *
 */
public class ProgressCenter {

    /**
     * 更新动作
     */
    private final static int ACTION_UPDATE = 1;

    /**
     * 销毁动作
     */
    private final static int ACTION_DISPOSE = 2;

    /**
     * 所有的进度数据信息
     */
    private static Map<String, Progress> progresses = Maps.newLinkedHashMap();

    /**
     * 所有的进度中心UI
     */
    private static Set<ProgressComposite> progressComposites = Sets.newHashSet();

    /**
     * 进度中心UI组件
     * 
     * @param composite
     */
    public static void addProgressComposites(ProgressComposite composite) {
        progressComposites.add(composite);
    }

    /**
     * 添加一个进度条
     * 
     * @param name        进度条名称，便于区分
     * @param description 进度条描述，显示在进度条之上
     * @param maximum     最大值
     * @param autoRemove  是否自动移除，true表示当进度条完成100%后自动移除。
     * @param cancelFunc  取消动作的回调函数
     */
    public static void add(String name, String description, int maximum, boolean autoRemove,
        Func<Object, Object> cancelFunc, Object cancelParam) {
        if (progresses.containsKey(name)) {
            // throw new RuntimeException("已有同名进度条");
        } else {
            Progress progress = new Progress();
            progress.setName(name);
            progress.setDescription(description);
            progress.setMaximum(maximum);
            progress.setAutoRemove(autoRemove);
            progress.setCancelFunc(cancelFunc);
            progress.setCancelParam(cancelParam);
            progresses.put(name, progress);

            notifyProgressComposite(name, ACTION_UPDATE);
        }
    }

    /**
     * 通知进度中心UI更新
     * 
     * @param barName 进度条名称
     * @param action  执行动作: ACTION_UPDATE 更新, ACTION_DISPOSE 销毁
     */
    private static void notifyProgressComposite(String barName, int action) {

        // 拿到对应的数据
        Progress progress = progresses.get(barName);

        // 循环所有的UI
        for (final ProgressComposite center : progressComposites) {
            if (center == null || center.isDisposed()) {
                progressComposites.remove(center);
                continue;
            }

            // 拿到对应的BarUnit
            ProgressBarUnit unit = center.getBarUnit(barName);
            if (unit == null) {
                if (progress != null) {
                    unit = center.addBarUnit(progress);
                }
            }
            if (action == ACTION_UPDATE) {
                unit.refreshUI(progress);
            } else if (action == ACTION_DISPOSE) {
                if (unit != null) {
                    unit.dispose();
                }
                // 移除进度条
                Map<String, ProgressBarUnit> units = center.getUnits();
                units.remove(barName);
                progresses.remove(barName);
            }
            center.refreshUI();
        }
    }

    public static void addSelection(String name, int incrSelection) {
        Progress progress = progresses.get(name);
        if (progress != null) {
            setSelection(name, progress.getSelection() + incrSelection);
        }
    }

    public static void setSelection(String name, int selection) {
        Progress progress = progresses.get(name);
        if (progress != null) {
            progress.setSelection(selection);
            if (selection >= progress.getMaximum() && progress.isAutoRemove()) {
                progresses.remove(name);
                notifyProgressComposite(name, ACTION_DISPOSE);
            } else {
                notifyProgressComposite(name, ACTION_UPDATE);
            }
        } else {
            notifyProgressComposite(name, ACTION_DISPOSE);
        }
    }

    public static void cancel(String name) throws Exception {
        Progress progress = progresses.get(name);
        // progress.execCancel();
        progresses.remove(name);
        notifyProgressComposite(name, ACTION_DISPOSE);
    }

}
